package exceptiontest

import (
	"errors"
	"gitee.com/stevenchin/gin_study/xorm/initxorm"
	"github.com/gin-gonic/gin"
	"github.com/xormplus/xorm"
	"log"
	"net/http"
	"time"
)

// CreateException 全局异常捕获测试
func CreateException(ctx *gin.Context) {
	param := ctx.Param("select")
	// 运行时无意抛出 panic
	if param == "runtime" {
		var slice = []int{1, 2, 3, 4, 5}
		// 超出数组下标范围
		slice[6] = 6
		ctx.String(http.StatusOK, "success")
	}
	// 抛出已知异常
	if param == "accord" {
		// 这里将mysql的连接信息配置错误
		if _, err := xorm.NewEngine(xorm.MYSQL_DRIVER,
			xorm.MYSQL_DRIVER+"://759b8d27dbc147789e0f79c7b098c0e3in01.internal.cn-east-3.mysql.rds.myhuaweicloud.com:3306/golang_db?charset=utf8"); err != nil {
			panic(any(err))
		} else {
			ctx.String(http.StatusOK, "success")
		}
	}
	// 抛出自定义异常
	if param == "custom" {
		e := errors.New("这是我自定义的异常")
		panic(any(e))
	}
	// 事务中抛出异常
	if param == "transaction" {
		session := initxorm.Engine.NewSession()
		// 延迟关闭事务
		defer func(session *xorm.Session) {
			err := session.Close()
			if err != nil {

			}
		}(session)
		// 创建一个事务
		err := session.Begin()
		if err != nil {
			ctx.String(http.StatusInternalServerError, "transaction begin error: "+err.Error())
			return
		}
		b := salesOrderChangedTemp{
			OrderNo:     "orderNo",
			ChangedJson: "changedJson",
		}
		log.Printf("this sid id is %d", b.Sid)
		if _, err = session.Insert(&b); err != nil {
			// 回滚事务
			_ = session.Rollback()
			ctx.String(http.StatusInternalServerError, "insert error: "+err.Error())
			return
		}
		log.Printf("this sid id is %d", b.Sid)
		b.ChangedJson = "changedJson is changed"
		time.Sleep(1 * time.Second)
		if _, err = session.ID(b.Sid).Update(&b); err != nil {
			_ = session.Rollback()
			ctx.String(http.StatusInternalServerError, "update error: "+err.Error())
			return
		}
		log.Printf("this sid id is %d", b.Sid)
		// 假设这里抛出了异常（需要放开注释掉的代码）。而未使用session.Rollback()主动回滚。通过控制台打印结果可以看到自动ROLL BACK 了
		// [xorm] [info]  2020/06/29 14:28:11.640109 [SQL] ROLL BACK [] - 17.842ms
		// 可以观察数据库，也没有插入数据以及修改后的数据
		//if err == nil {
		//	err := errors.New("在事务中抛出了异常")
		//	panic(any(err))
		//}
		if _, err = session.ID(b.Sid).Delete(&salesOrderChangedTemp{}); err != nil {
			_ = session.Rollback()
			ctx.String(http.StatusInternalServerError, "delete error: "+err.Error())
			return
		}
		// 提交事务
		if err = session.Commit(); err != nil {
			ctx.String(http.StatusInternalServerError, "transaction commit error: "+err.Error())
			return
		}
		ctx.String(http.StatusOK, "transaction success")
	}
}


// 测试结构体
// 结构体的命名和字段命名需要根据 engine 中设置的规则来。这里见：xorm/xormplus/orm1.go:24 代码块对应设置
// Tips：字段名称需要全部以大写开头，否则在 xorm 中反射时获取不到字段名
// 该结构体对应的表结构为：
// create table t_sales_order_changed_temp
//(
//    sid         bigint auto_increment comment '主键ID'
//        primary key,
//    orderNo     varchar(50)   null,
//    changedJson varchar(2500) not null comment '修改前数据',
//    deleted     int           null comment '是否删除，0否1是',
//    createTime  datetime      null comment '创建时间',
//    updateTime  datetime      null comment '更新时间',
//    createName  varchar(62)   null comment '创建名称',
//    createNo    varchar(32)   null comment '创建人工号',
//    updateNo    varchar(32)   null comment '更新人工号',
//    updateName  varchar(62)   null comment '更新人名称'
//)
type salesOrderChangedTemp struct {
	// 设置 sid 为 Primary Key，且自增 autoincr
	Sid int64 `xorm:"'sid' pk autoincr"`
	// 设置 orderNo 长度为 50，且不能为空
	OrderNo     string `xorm:"'orderNo' varchar(50) notnull"`
	ChangedJson string `xorm:"'changedJson' varchar(2500) notnull"`
	// 设置 deleted 不能为空，且默认值为 0
	Deleted int8 `xorm:"'deleted' notnull default(0)"`
	// 如果设置的 mapper 还是不能和数据库匹配，可以在 tag 中设置别名，例如这里的 Time -> createTime
	// created 这个Field将在Insert时自动赋值为当前时间
	// TIPS：默认xorm采用Local时区，所以默认调用的time.Now()会先被转换成对应的时区。要改变xorm的时区，可以使用： orm1.Engine.TZLocation, _ = time.LoadLocation("Asia/Shanghai")
	Time int64 `xorm:"created DATETIME 'createTime'"`
	// updated 这个Field将在Insert或Update时自动赋值为当前时间
	UpdateTime int64 `xorm:"updated DATETIME 'updateTime'"`
}
